<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>像素果</title>

    <link rel="icon" href="./Logo/Logo.png" type="image/png">
    <script src="https://cdn.tailwindcss.com"></script>
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        'bg-dark': '#1e1e1e',
                        'panel-dark': '#2d2d2d',
                        'border-dark': '#444',
                        'text-light': '#eee',
                        'text-muted': '#aaa',
                        'primary': '#4a8cff',
                    }
                }
            }
        }
    </script>
    <link rel="stylesheet" href="css/custom.css">
</head>
<body class="font-sans bg-bg-dark text-text-light m-0 p-5 leading-relaxed">
    
    <div class="flex gap-4 max-w-[1600px] mx-auto h-[calc(100vh-40px)]">
        <div class="w-[280px] flex flex-col gap-4 overflow-y-auto left-panel">
            <div class="bg-panel-dark rounded-lg p-4 shadow-lg panel">
                <div class="flex justify-between items-center mb-4 pb-3 border-b border-border-dark">
                    <h3 class="m-0 text-lg text-text-light">文件上传</h3>
                    <button id="settings-button" class="bg-transparent border border-border-dark text-text-light rounded px-3 py-1.5 cursor-pointer text-xl transition-all duration-200 flex items-center justify-center relative overflow-hidden settings-button hover:bg-panel-dark hover:border-gray-600 hover:text-white active:scale-95" title="设置">⚙️</button>
                </div>
                <div class="bg-panel-dark border-2 border-dashed border-border-dark rounded-md p-4 text-center transition-all duration-300 file-input hover:border-gray-600 hover:  ">
                    <input type="file" id="raw-file" accept=".cr2,.nef,.arw,.dng,.raw,.rw2">
                    <label for="raw-file" class="block px-4 py-2.5 bg-gray-700 text-white rounded cursor-pointer font-medium transition-colors duration-200 hover:bg-gray-600">选择 RAW 文件</label>
                    <div class="mt-2.5 text-text-muted text-sm" id="file-name">未选择文件</div>
                </div>
            </div>
            
            <div class="bg-panel-dark rounded-lg p-4 shadow-lg panel">
                <div class="flex justify-between items-center mb-4 pb-3 border-b border-border-dark">
                    <h3 class="m-0 text-lg text-text-light">基本设置</h3>
                </div>
                <div class="my-2.5 checkbox-group">
                    <label class="flex items-center gap-2 cursor-pointer text-sm text-text-light">
                        <input type="checkbox" id="use-auto-wb" checked class="w-4 h-4 accent-primary">
                        自动白平衡
                    </label>
                </div>
                <div class="my-2.5 checkbox-group">
                    <label class="flex items-center gap-2 cursor-pointer text-sm text-text-light">
                        <input type="checkbox" id="use-camera-wb" class="w-4 h-4 accent-primary">
                        相机白平衡
                    </label>
                </div>
                <div class="flex gap-2 my-4 button-group">
                    <button id="fullscreen-view-button" class="px-3 py-2 bg-blue-700 text-white border-none rounded cursor-pointer text-sm transition-colors duration-200 hover:bg-blue-800 disabled:opacity-50 disabled:cursor-not-allowed" disabled>查看大屏图片</button>
                </div>
                <div class="slider-group">
                    <label for="brightness" class="block text-sm text-text-light">亮度</label>
                    <div class="flex items-center gap-2.5 slider-wrapper">
                        <input type="range" id="brightness" min="0.1" max="4" step="0.1" value="1" class="flex-1">
                        <span class="w-12 text-right font-mono text-gray-300" id="brightness-value">1.0</span>
                    </div>
                </div>
                <div class="slider-group">
                    <label for="exposure" class="block text-sm text-text-light">曝光补偿</label>
                    <div class="flex items-center gap-2.5 slider-wrapper">
                        <input type="range" id="exposure" min="-2" max="2" step="0.1" value="0" class="flex-1">
                        <span class="w-12 text-right font-mono text-gray-300" id="exposure-value">0.0</span>
                    </div>
                </div>
                <div class="slider-group">
                    <label for="saturation" class="block text-sm text-text-light">饱和度</label>
                    <div class="flex items-center gap-2.5 slider-wrapper">
                        <input type="range" id="saturation" min="0" max="300" step="1" value="100" class="flex-1">
                        <span class="w-12 text-right font-mono text-gray-300" id="saturation-value">100</span>
                    </div>
                </div>
                <div class="slider-group">
                    <label for="contrast" class="block text-sm text-text-light">对比度</label>
                    <div class="flex items-center gap-2.5 slider-wrapper">
                        <input type="range" id="contrast" min="-50" max="50" step="1" value="0" class="flex-1">
                        <span class="w-12 text-right font-mono text-gray-300" id="contrast-value">0</span>
                    </div>
                </div>
                
                <div class="my-4 filter-group">
                    <label for="filter-select" class="block mb-2 text-sm text-text-light">预设滤镜</label>
                    <div class="flex gap-2 items-center filter-controls">
                        <select id="filter-select" class="flex-1 px-2 py-1.5 bg-stone-700   rounded text-sm filter-select focus:outline-none focus:border-primary">
                            <option value="none">无滤镜</option>
                        </select>
                        <button id="save-filter-button" class="px-3 py-1.5 bg-blue-700 text-white border-none rounded cursor-pointer text-xs transition-colors duration-200 hover:bg-blue-800 disabled:opacity-50 disabled:cursor-not-allowed" disabled>保存当前配置</button>
                    </div>
                </div>
                <div class="flex gap-2 my-4 button-group">
                    <button id="reset-button" class="px-3 py-2 bg-red-800 text-white border-none rounded cursor-pointer text-sm transition-all duration-200 hover:bg-red-900 disabled:opacity-50 disabled:cursor-not-allowed" disabled>重置</button>
                    <button id="export-png-button" class="px-3 py-2 bg-blue-700 text-white border-none rounded cursor-pointer text-sm transition-all duration-200 hover:bg-blue-800 disabled:opacity-50 disabled:cursor-not-allowed" disabled>导出 PNG</button>
                    <button id="export-jpeg-button" class="px-3 py-2 bg-blue-700 text-white border-none rounded cursor-pointer text-sm transition-all duration-200 hover:bg-blue-800 disabled:opacity-50 disabled:cursor-not-allowed" disabled>导出 JPEG</button>
                </div>
            </div>
        </div>
        
        <div class="flex-1 min-h-[600px] center-panel">
            <div class="bg-panel-dark rounded-lg overflow-hidden relative h-full flex items-center justify-center image-container">
                <canvas id="image-canvas" class="max-w-full max-h-full object-contain shadow-lg"></canvas>
                <div class="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 text-text-muted text-xl" id="status-message">请上传 RAW 文件以查看图像</div>
            </div>
        </div>
        
        <div class="w-[280px] flex flex-col gap-4 overflow-y-auto right-panel">
            <div class="bg-panel-dark rounded-lg p-4 shadow-lg panel">
                <div class="flex border-b border-border-dark mb-4 tabs">
                    <button class="px-4 py-2 bg-transparent border-none text-text-muted cursor-pointer relative tab active hover:text-text-light" data-tab="color">颜色调整</button>
                    <button class="px-4 py-2 bg-transparent border-none text-text-muted cursor-pointer relative tab hover:text-text-light" data-tab="detail">细节处理</button>
                    <button class="px-4 py-2 bg-transparent border-none text-text-muted cursor-pointer relative tab hover:text-text-light" data-tab="color-replace">颜色替换</button>
                </div>
                
                <div class="tab-content active" id="color-tab">
                    <div class="color-adjustments">
                        <div class="my-3 color-slider">
                            <label for="red-tint" class="block mb-1.5 text-sm text-text-light">红色色调</label>
                            <div class="flex items-center gap-2.5 slider-wrapper">
                                <input type="range" id="red-tint" min="-100" max="100" step="1" value="0" class="flex-1">
                                <span class="w-12 text-right font-mono text-gray-300" id="red-tint-value">0</span>
                            </div>
                        </div>
                        <div class="my-3 color-slider">
                            <label for="green-tint" class="block mb-1.5 text-sm text-text-light">绿色色调</label>
                            <div class="flex items-center gap-2.5 slider-wrapper">
                                <input type="range" id="green-tint" min="-100" max="100" step="1" value="0" class="flex-1">
                                <span class="w-12 text-right font-mono text-gray-300" id="green-tint-value">0</span>
                            </div>
                        </div>
                        <div class="my-3 color-slider">
                            <label for="blue-tint" class="block mb-1.5 text-sm text-text-light">蓝色色调</label>
                            <div class="flex items-center gap-2.5 slider-wrapper">
                                <input type="range" id="blue-tint" min="-100" max="100" step="1" value="0" class="flex-1">
                                <span class="w-12 text-right font-mono text-gray-300" id="blue-tint-value">0</span>
                            </div>
                        </div>
                        <div class="my-3 color-slider">
                            <label for="highlights" class="block mb-1.5 text-sm text-text-light">高光</label>
                            <div class="flex items-center gap-2.5 slider-wrapper">
                                <input type="range" id="highlights" min="-50" max="50" step="1" value="0" class="flex-1">
                                <span class="w-12 text-right font-mono text-gray-300" id="highlights-value">0</span>
                            </div>
                        </div>
                        <div class="my-3 color-slider">
                            <label for="shadows" class="block mb-1.5 text-sm text-text-light">阴影</label>
                            <div class="flex items-center gap-2.5 slider-wrapper">
                                <input type="range" id="shadows" min="-50" max="50" step="1" value="0" class="flex-1">
                                <span class="w-12 text-right font-mono text-gray-300" id="shadows-value">0</span>
                            </div>
                        </div>
                        <div class="my-3 color-slider">
                            <label for="whites" class="block mb-1.5 text-sm text-text-light">白色</label>
                            <div class="flex items-center gap-2.5 slider-wrapper">
                                <input type="range" id="whites" min="0" max="100" step="1" value="100" class="flex-1">
                                <span class="w-12 text-right font-mono text-gray-300" id="whites-value">100</span>
                            </div>
                        </div>
                    </div>
                </div>
                
                <div class="hidden tab-content" id="detail-tab">
                    <div class="flex flex-col gap-4 detail-controls">
                        <div class="slider-group">
                            <label for="sharpness" class="block text-sm text-text-light">锐化</label>
                            <div class="flex items-center gap-2.5 slider-wrapper">
                                <input type="range" id="sharpness" min="0" max="100" step="1" value="0" class="flex-1">
                                <span class="w-12 text-right font-mono text-gray-300" id="sharpness-value">0</span>
                            </div>
                        </div>
                        <div class="slider-group">
                            <label for="noise-reduction" class="block text-sm text-text-light">减少杂色</label>
                            <div class="flex items-center gap-2.5 slider-wrapper">
                                <input type="range" id="noise-reduction" min="0" max="100" step="1" value="0" class="flex-1">
                                <span class="w-12 text-right font-mono text-gray-300" id="noise-reduction-value">0</span>
                            </div>
                        </div>
                        <div class="slider-group">
                            <label for="noise-reduction-type" class="block text-sm text-text-light ">降噪算法</label>
                            <select id="noise-reduction-type" class="w-full px-2 py-1.5 bg-stone-700 text-text-light  border-none rounded text-sm control-select focus:outline-none focus:border-primary">
                                <option value="mean">均值滤波 (标准)</option>
                                <option value="median">中值滤波 (椒盐噪点)</option>
                                <option value="gaussian">高斯滤波 (平滑)</option>
                            </select>
                        </div>
                        <div class="slider-group">
                            <label for="detail-preservation" class="block text-sm text-text-light">细节保留</label>
                            <div class="flex items-center gap-2.5 slider-wrapper">
                                <input type="range" id="detail-preservation" min="0" max="100" step="1" value="50" class="flex-1">
                                <span class="w-12 text-right font-mono text-gray-300" id="detail-preservation-value">50</span>
                            </div>
                        </div>
                        <div class="slider-group">
                            <label for="texture" class="block text-sm text-text-light">纹理/清晰度</label>
                            <div class="flex items-center gap-2.5 slider-wrapper">
                                <input type="range" id="texture" min="-50" max="50" step="1" value="0" class="flex-1">
                                <span class="w-12 text-right font-mono text-gray-300" id="texture-value">0</span>
                            </div>
                        </div>
                        <div class="slider-group">
                            <label for="face-brightening" class="block text-sm text-text-light">面部美白</label>
                            <div class="flex items-center gap-2.5 slider-wrapper">
                                <input type="range" id="face-brightening" min="0" max="100" step="1" value="0" class="flex-1">
                                <span class="w-12 text-right font-mono text-gray-300" id="face-brightening-value">0</span>
                            </div>
                        </div>
                        <div class="slider-group">
                            <label for="face-smoothness" class="block text-sm text-text-light">过渡平滑度</label>
                            <div class="flex items-center gap-2.5 slider-wrapper">
                                <input type="range" id="face-smoothness" min="0" max="100" step="1" value="50" class="flex-1">
                                <span class="w-12 text-right font-mono text-gray-300" id="face-smoothness-value">50</span>
                            </div>
                        </div>
                    </div>
                </div>
                
                <div class="hidden tab-content" id="color-replace-tab">
                    <div class="color-replace-controls">
                        <div class="mb-5 p-4    rounded-md border border-border-dark color-range-selector">
                            <h4 class="m-0 mb-4 text-base text-text-light">颜色范围选择</h4>
                            <div class="flex gap-2.5 mb-4 color-inputs">
                                <div class="flex-1 color-input-group">
                                    <input type="color" id="color-range-start" value="#ff0000" class="w-full h-9 border border-gray-600 rounded bg-transparent cursor-pointer transparent">
                                    <label for="color-range-start" class="block mb-1.5 text-xs text-text-muted">起始颜色</label>
                                </div>
                                <div class="flex-1 color-input-group">
                                    <input type="color" id="color-range-end" value="#0000ff" class="w-full h-9 border border-gray-600 rounded bg-transparent cursor-pointer transparent">
                                    <label for="color-range-end" class="block mb-1.5 text-xs text-text-muted">结束颜色</label>
                                </div>
                            </div>
                            
                            <div class="relative h-6 my-4 bg-gray-700 rounded border border-gray-600 range-wrapper" id="colorRangeContainer">
                                <div class="absolute top-0 left-0 right-0 bottom-0 rounded pointer-events-none gradient-track" id="colorGradientTrack"></div>
                                <input type="range" id="colorSlider1" class="absolute w-full top-0 left-0 bg-transparent range-slider transparent" min="0" max="100" value="0" style="z-index: 2;">
                                <input type="range" id="colorSlider2" class="absolute w-full top-0 left-0 bg-transparent range-slider transparent" min="0" max="100" value="100" style="z-index: 3;">
                            </div>
                            
                        </div>
                        
                        <div class="mb-5 p-4    rounded-md border border-border-dark target-color-settings">
                            <h4 class="m-0 mb-4 text-base text-text-light">目标颜色范围</h4>
                            <div class="flex gap-2.5 mb-4 color-inputs">
                                <div class="flex-1 color-input-group">
                                    <input type="color" id="target-color-start" value="#00ff00" class="w-full h-9 border border-gray-600 rounded bg-transparent cursor-pointer transparent">
                                    <label for="target-color-start" class="block mb-1.5 text-xs text-text-muted">目标起始颜色</label>
                                </div>
                                <div class="flex-1 color-input-group">
                                    <input type="color" id="target-color-end" value="#ffff00" class="w-full h-9 border border-gray-600 rounded bg-transparent cursor-pointer transparent">
                                    <label for="target-color-end" class="block mb-1.5 text-xs text-text-muted">目标结束颜色</label>
                                </div>
                            </div>
                            
                            <div class="relative h-6 my-4 bg-gray-700 rounded border border-gray-600 range-wrapper" id="targetColorRangeContainer">
                                <div class="absolute top-0 left-0 right-0 bottom-0 rounded pointer-events-none gradient-track" id="targetColorGradientTrack"></div>
                            </div>
                            
                            <div class="my-4 mix-ratio">
                                <label for="mixRatio" class="block text-sm text-text-light">替换强度</label>
                                <div class="flex items-center gap-2.5 slider-wrapper">
                                    <input type="range" id="mixRatio" min="0" max="100" step="1" value="100" class="flex-1">
                                    <span class="w-12 text-right font-mono text-gray-300" id="mixRatio-value">100%</span>
                                </div>
                            </div>
                            
                            <div class="my-4 tolerance-setting">
                                <label for="colorTolerance" class="block text-sm text-text-light">颜色容差</label>
                                <div class="flex items-center gap-2.5 slider-wrapper">
                                    <input type="range" id="colorTolerance" min="10" max="200" step="5" value="60" class="flex-1">
                                    <span class="w-12 text-right font-mono text-gray-300" id="colorTolerance-value">60</span>
                                </div>
                                <div class="mt-1.5 text-xs text-text-muted tolerance-description">
                                    <small>容差值越小，颜色匹配越精确；容差值越大，匹配范围越广</small>
                                </div>
                            </div>
                        </div>
                        
                        <div class="flex gap-2.5 my-4 color-replace-actions">
                            <button id="previewColorReplace" class="flex-1 px-3 py-2 bg-gray-700 text-white border-none rounded cursor-pointer text-sm transition-colors duration-200 hover:bg-gray-600 action-button">预览效果</button>
                            <button id="applyColorReplace" class="flex-1 px-3 py-2 bg-primary text-white border-none rounded cursor-pointer text-sm transition-colors duration-200 hover:bg-blue-600 action-button primary">应用替换</button>
                            <button id="undoColorReplace" class="flex-1 px-3 py-2 bg-gray-700 text-white border-none rounded cursor-pointer text-sm transition-colors duration-200 hover:bg-gray-600 action-button">撤销</button>
                        </div>
                        
                        <div class="my-4 p-3 bg-green-900 rounded border-l-4 border-green-600 color-replace-result" id="colorReplaceResult" style="display: none;">
                            <div class="text-green-500 text-sm font-medium result-info">
                                <span id="replacedPixelsCount">0</span> 个像素已替换
                            </div>
                        </div>
                        
                        <div class="mt-5 color-replace-history">
                            <h4 class="m-0 mb-2.5 text-base text-text-light">替换历史</h4>
                            <div class="max-h-[250px] overflow-y-auto mt-4 border border-border-dark rounded history-table-container">
                                <table id="colorReplaceTable" class="w-full border-collapse text-xs bg-panel-dark history-table">
                                    <thead>
                                        <tr>
                                            <th class="p-2 border border-border-dark text-left bg-gray-700 sticky top-0 font-semibold text-text-light">起始颜色</th>
                                            <th class="p-2 border border-border-dark text-left bg-gray-700 sticky top-0 font-semibold text-text-light">结束颜色</th>
                                            <th class="p-2 border border-border-dark text-left bg-gray-700 sticky top-0 font-semibold text-text-light">目标起始颜色</th>
                                            <th class="p-2 border border-border-dark text-left bg-gray-700 sticky top-0 font-semibold text-text-light">目标结束颜色</th>
                                            <th class="p-2 border border-border-dark text-left bg-gray-700 sticky top-0 font-semibold text-text-light">替换强度</th>
                                            <th class="p-2 border border-border-dark text-left bg-gray-700 sticky top-0 font-semibold text-text-light">容差</th>
                                            <th class="p-2 border border-border-dark text-left bg-gray-700 sticky top-0 font-semibold text-text-light">替换像素</th>
                                            <th class="p-2 border border-border-dark text-left bg-gray-700 sticky top-0 font-semibold text-text-light">操作</th>
                                        </tr>
                                    </thead>
                                    <tbody id="colorReplaceTableBody">
                                    </tbody>
                                </table>
                            </div>
                        </div>
                    </div>
                </div>
            </div>

            <div id="image-detail-panel" class="mt-4 bg-panel-dark rounded-lg p-4 border border-border-dark shadow-lg relative z-10 overflow-visible image-detail-panel">
                <div class="mb-4 pb-3 border-b border-border-dark detail-header">
                    <h4 class="m-0 text-lg text-text-light">图片细节</h4>
                </div>
                <div class="flex gap-4 items-start detail-content relative z-20">
                    <div class="w-24 h-24 border border-border-dark  rounded overflow-hidden flex-shrink-0 zoom-preview">
                        <canvas id="zoom-canvas" width="200" height="200" class="w-full h-full"></canvas>
                    </div>
                    <div class="flex-1 min-w-0 pixel-info relative z-20">
                        <div class="flex mb-2 items-center min-h-5 info-item relative z-20">
                            <span class="w-[60px] text-text-muted text-sm flex-shrink-0 label">位置:</span>
                            <span class="text-text-light font-mono text-sm break-all value" id="pixel-position">请上传图片</span>
                        </div>
                        <div class="flex mb-2 items-center min-h-5 info-item relative z-20">
                            <span class="w-[60px] text-text-muted text-sm flex-shrink-0 label">RGB:</span>
                            <span class="text-text-light font-mono text-sm break-all value" id="pixel-rgb">-</span>
                        </div>
                        <div class="flex mb-2 items-center min-h-5 info-item relative z-20">
                            <span class="w-[60px] text-text-muted text-sm flex-shrink-0 label">亮度:</span>
                            <span class="text-text-light font-mono text-sm break-all value" id="pixel-brightness">-</span>
                        </div>
                        <div class="flex mb-2 items-center min-h-5 info-item relative z-20">
                            <span class="w-[60px] text-text-muted text-sm flex-shrink-0 label">色相:</span>
                            <span class="text-text-light font-mono text-sm break-all value" id="pixel-hue">-</span>
                        </div>
                    </div>
                </div>
            </div>

            <div class="mt-5 histogram-panel">
                <div class="bg-panel-dark rounded-lg p-4 shadow-lg panel">
                    <div class="flex justify-between items-center mb-4 pb-3 border-b border-border-dark">
                        <h3 class="m-0 text-lg text-text-light">直方图</h3>
                        <div class="flex gap-2.5 mb-2.5 histogram-controls">
                            <button class="px-2.5 py-1.5 text-xs histogram-btn active bg-primary" data-mode="luminance">亮度</button>
                            <button class="px-2.5 py-1.5 text-xs histogram-btn" data-mode="rgb">RGB</button>
                        </div>
                    </div>
                    <canvas id="histogram-canvas"></canvas>
                </div>
            </div>
            
            <div class="bg-panel-dark rounded-lg p-4 shadow-lg panel">
                <div class="flex justify-between items-center mb-4 pb-3 border-b border-border-dark">
                    <h3 class="m-0 text-lg text-text-light">图像元数据</h3>
                </div>
                <div class="font-mono text-xs text-gray-300 max-h-[200px] overflow-y-auto whitespace-pre-wrap metadata" id="metadata-output">请上传 RAW 文件以查看元数据</div>
            </div>
        </div>
    </div>

    <!-- 设置遮罩层 -->
    <div id="settings-modal" class="hidden fixed top-0 left-0 w-full h-full bg-black/0 backdrop-blur-0 z-[1000] justify-center items-center opacity-0 invisible transition-all duration-[400ms] settings-modal">
        <div class="bg-panel-dark rounded-xl w-[90%] max-w-[600px] h-[60vh] overflow-hidden flex flex-col shadow-2xl scale-90 translate-y-5 opacity-0 transition-all duration-[400ms] settings-modal-content">
            <div class="flex justify-between items-center p-5 border-b border-border-dark flex-shrink-0 settings-modal-header">
                <h3 class="m-0 text-xl text-text-light">设置</h3>
                <button class="bg-transparent border-none text-text-light text-2xl cursor-pointer p-0 w-8 h-8 flex items-center justify-center rounded transition-all duration-200 hover:bg-white/10 hover:text-white settings-modal-close" id="settings-modal-close">×</button>
            </div>
            <div class="flex p-0 text-text-light flex-1 overflow-hidden settings-modal-body">
                <div class="w-[100px]  border-r border-border-dark flex flex-col p-5 flex-shrink-0 settings-sidebar">
                    <button class="w-full px-2.5 py-3 bg-transparent border-none text-text-muted text-center cursor-pointer text-sm transition-all duration-200 border-l-[3px] border-transparent relative flex items-center justify-center hover:bg-white/5 hover:text-text-light settings-sidebar-item active bg-primary/10 text-primary border-l-primary" data-tab="ai-provider">
                        <span class="block text-center w-full">AI设置</span>
                    </button>
                    <button class="w-full px-2.5 py-3 bg-transparent border-none text-text-muted text-center cursor-pointer text-sm transition-all duration-200 border-l-[3px] border-transparent relative flex items-center justify-center hover:bg-white/5 hover:text-text-light settings-sidebar-item" data-tab="about">
                        <span class="block text-center w-full">关于</span>
                    </button>
                </div>
                <div class="flex-1 p-5 overflow-y-auto min-h-0 settings-content">
                    <div class="settings-tab-content active" id="ai-provider-tab">
                        <div class="mb-5 settings-form-group">
                            <label for="ai-provider" class="block mb-2 text-sm text-text-light font-medium">AI 模型厂商</label>
                            <select id="ai-provider" class="w-full px-3 py-2.5 bg-panel-dark border border-border-dark rounded-md text-text-light text-sm cursor-pointer transition-all duration-200 hover:border-gray-600 focus:outline-none focus:border-primary focus:shadow-[0_0_0_3px_rgba(74,158,255,0.1)] disabled:opacity-50 disabled:cursor-not-allowed settings-select">
                                <option value="alibaba" selected>阿里巴巴</option>
                            </select>
                        </div>
                        <div class="mb-5 settings-form-group">
                            <label for="ai-model" class="block mb-2 text-sm text-text-light font-medium">模型名称</label>
                            <select id="ai-model" class="w-full px-3 py-2.5 bg-panel-dark border border-border-dark rounded-md text-text-light text-sm cursor-pointer transition-all duration-200 hover:border-gray-600 focus:outline-none focus:border-primary focus:shadow-[0_0_0_3px_rgba(74,158,255,0.1)] disabled:opacity-50 disabled:cursor-not-allowed settings-select">
                                <option value="">请选择模型</option>
                                <option value="qwen-max">通义千问 Max</option>
                                <option value="qwen-plus">通义千问 Plus</option>
                                <option value="qwen-turbo">通义千问 Turbo</option>
                                <option value="qwen-7b">Qwen 7B</option>
                            </select>
                        </div>
                        <div class="mb-5 settings-form-group">
                            <label for="api-key" class="block mb-2 text-sm text-text-light font-medium">API Key</label>
                            <input type="password" id="api-key" class="w-full px-3 py-2.5 bg-panel-dark border border-border-dark rounded-md text-text-light text-sm transition-all duration-200 hover:border-gray-600 focus:outline-none focus:border-primary focus:shadow-[0_0_0_3px_rgba(74,158,255,0.1)] disabled:opacity-50 disabled:cursor-not-allowed box-border settings-input" placeholder="请输入API Key">
                        </div>
                        <div class="flex justify-end items-center pt-5 mt-5 settings-tab-footer">
                            <button class="px-6 py-2.5 bg-primary text-white border-none rounded-md text-sm font-medium cursor-pointer transition-all duration-200 hover:bg-blue-600 hover:-translate-y-0.5 hover:shadow-[0_4px_12px_rgba(74,140,255,0.3)] active:translate-y-0 active:shadow-[0_2px_6px_rgba(74,140,255,0.2)] settings-confirm-button" id="settings-confirm-button">确定</button>
                        </div>
                    </div>
                    <div class="hidden settings-tab-content" id="about-tab">
                        <div class="max-w-[600px] about-content">
                            <div class="mb-8 text-center pb-5 border-b border-border-dark about-header">
                                <h2 class="m-0 mb-2.5 text-3xl text-text-light">像素果</h2>
                                <p class="m-0 text-text-muted text-sm about-version">版本 1.2.1</p>
                            </div>
                            <div class="mb-8 leading-relaxed about-description">
                                <p class="my-2.5 text-text-light">像素果是一款强大的 RAW 图像处理工具，支持多种 RAW 格式文件的读取和处理。</p>
                                <p class="my-2.5 text-text-light">提供丰富的图像调整功能，包括颜色调整、细节处理、滤镜效果等。</p>
                            </div>
                            <div class="mb-8 about-features">
                                <h3 class="m-0 mb-4 text-xl text-text-light">主要功能</h3>
                                <ul class="m-0 pl-5 text-text-light leading-relaxed">
                                    <li class="my-2">支持多种 RAW 格式（CR2, NEF, ARW, DNG, RAW, RW2）</li>
                                    <li class="my-2">实时图像调整和预览</li>
                                    <li class="my-2">颜色调整和细节处理</li>
                                    <li class="my-2">滤镜预设和自定义配置</li>
                                    <li class="my-2">颜色替换功能</li>
                                    <li class="my-2">直方图显示</li>
                                    <li class="my-2">图像导出（PNG/JPEG）</li>
                                </ul>
                            </div>
                            <div class="mt-8 pt-5 border-t border-border-dark text-center about-footer">
                                <p class="m-0 text-text-muted text-sm">© 2025 像素果. All rights reserved.</p>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script type="module">
        import LibRaw from './index.js';
        import { initColorModule, applyColorAdjustments, updateWhiteBalanceCoefficients, applyContrast, registerColorEventListeners } from './Files/color.js';
        import { applyUnsharpMask, applySharpness, applyNoiseReduction, applyFaceBrightening } from './Files/Details.js';
        import { initSliderManager, addSliderEventListenersBatch } from './Files/SliderManager.js';
        import { exportPNG, exportJPEG } from './Files/exportImage.js';
        import { initColorReplace } from './Files/Replacecolor.js';
        import { initFilterModule } from './Files/Filter.js';
        import { initChartModule } from './Files/Chart.js';
        import { initAiModule, saveApiKeyToStorage, saveAiProviderToStorage, saveAiModelToStorage, updateAiModels, aiModels } from './Files/Ai.js';
        
        // 找到页面上的各个元素
        const rawFileInput = document.getElementById('raw-file');
        const fileName = document.getElementById('file-name');
        const metadataOutput = document.getElementById('metadata-output');
        const canvas = document.getElementById('image-canvas');
        // 用sRGB颜色空间，这样显示和导出颜色才不会跑偏
        const ctx = canvas.getContext('2d', { colorSpace: 'srgb' });
        const statusMessage = document.getElementById('status-message');
        const resetButton = document.getElementById('reset-button');
        const exportPngButton = document.getElementById('export-png-button');
        const exportJpegButton = document.getElementById('export-jpeg-button');
        const fullscreenViewButton = document.getElementById('fullscreen-view-button');
        const imageDetailPanel = document.getElementById('image-detail-panel');
        const zoomCanvas = document.getElementById('zoom-canvas');
        const pixelPosition = document.getElementById('pixel-position');
        const pixelRgb = document.getElementById('pixel-rgb');
        const pixelBrightness = document.getElementById('pixel-brightness');
        const pixelHue = document.getElementById('pixel-hue');
        
        // 图片细节面板的显示模式，固定还是跟随鼠标
        let isDetailFixed = false;
        let fixedPosition = { x: 0, y: 0 };
        let lastUpdateTime = 0;
        const UPDATE_THROTTLE = 16; // 大概60帧每秒，够用了
        
        // 把调色用的控件都找出来
        const useAutoWbCheckbox = document.getElementById('use-auto-wb');
        const useCameraWbCheckbox = document.getElementById('use-camera-wb');
        const brightnessSlider = document.getElementById('brightness');
        const brightnessValue = document.getElementById('brightness-value');
        const exposureSlider = document.getElementById('exposure');
        const exposureValue = document.getElementById('exposure-value');
        const saturationSlider = document.getElementById('saturation');
        const saturationValue = document.getElementById('saturation-value');
        const sharpnessSlider = document.getElementById('sharpness');
        const sharpnessValue = document.getElementById('sharpness-value');
        const noiseReductionSlider = document.getElementById('noise-reduction');
        const noiseReductionValue = document.getElementById('noise-reduction-value');
        const textureSlider = document.getElementById('texture');
        const textureValue = document.getElementById('texture-value');
        const contrastSlider = document.getElementById('contrast');
        const contrastValue = document.getElementById('contrast-value');
        const redTintSlider = document.getElementById('red-tint');
        const greenTintSlider = document.getElementById('green-tint');
        const blueTintSlider = document.getElementById('blue-tint');
        const redTintValue = document.getElementById('red-tint-value');
        const greenTintValue = document.getElementById('green-tint-value');
        const blueTintValue = document.getElementById('blue-tint-value');
        const highlightsSlider = document.getElementById('highlights');
        const highlightsValue = document.getElementById('highlights-value');
        const shadowsSlider = document.getElementById('shadows');
        const shadowsValue = document.getElementById('shadows-value');
        const whitesSlider = document.getElementById('whites');
        const whitesValue = document.getElementById('whites-value');
        const noiseReductionTypeSelect = document.getElementById('noise-reduction-type');
        const detailPreservationSlider = document.getElementById('detail-preservation');
        const detailPreservationValue = document.getElementById('detail-preservation-value');
        const faceBrighteningSlider = document.getElementById('face-brightening');
        const faceBrighteningValue = document.getElementById('face-brightening-value');
        const faceSmoothnessSlider = document.getElementById('face-smoothness');
        const faceSmoothnessValue = document.getElementById('face-smoothness-value');
        const filterSelect = document.getElementById('filter-select');
        const saveFilterButton = document.getElementById('save-filter-button');
        const settingsButton = document.getElementById('settings-button');
        const settingsModal = document.getElementById('settings-modal');
        const settingsModalClose = document.getElementById('settings-modal-close');
        const aiProviderSelect = document.getElementById('ai-provider');
        const aiModelSelect = document.getElementById('ai-model');
        const apiKeyInput = document.getElementById('api-key');
        const settingsConfirmButton = document.getElementById('settings-confirm-button');
        
        // 初始化AI模块
        initAiModule({
            apiKeyInput,
            providerSelect: aiProviderSelect,
            modelSelect: aiModelSelect
        });
        
        // 确定按钮点击事件 - 保存所有设置到localStorage
        if (settingsConfirmButton) {
            settingsConfirmButton.addEventListener('click', (e) => {
                e.preventDefault();
                e.stopPropagation();
                
                // 保存API Key
                saveApiKeyToStorage(apiKeyInput);
                
                // 保存AI厂商
                saveAiProviderToStorage(aiProviderSelect);
                
                // 保存AI模型
                saveAiModelToStorage(aiModelSelect);
                
                // 更新模型列表（确保模型选择器状态正确）
                updateAiModels(aiProviderSelect, aiModelSelect, aiModels);
                
                // 关闭设置模态框
                closeSettingsModal();
            });
        }
        
        // 标签页相关的元素
        const tabs = document.querySelectorAll('.tab');
        const tabContents = document.querySelectorAll('.tab-content');
        
        // 设置遮罩层控制
        function openSettingsModal() {
            // 先设置display，让元素可见
            settingsModal.style.display = 'flex';
            // 使用requestAnimationFrame确保动画能正确触发
            requestAnimationFrame(() => {
                settingsModal.classList.add('show');
            });
        }
        
        function closeSettingsModal() {
            // 移除show类，触发关闭动画
            settingsModal.classList.remove('show');
            // 等待动画完成后再隐藏元素
            setTimeout(() => {
                if (!settingsModal.classList.contains('show')) {
                    settingsModal.style.display = 'none';
                }
            }, 400); // 与CSS动画时长一致
        }
        
        // 打开设置遮罩层
        settingsButton.addEventListener('click', openSettingsModal);
        
        // 关闭设置遮罩层
        settingsModalClose.addEventListener('click', closeSettingsModal);
        
        // 点击遮罩层外部关闭
        settingsModal.addEventListener('click', (e) => {
            if (e.target === settingsModal) {
                closeSettingsModal();
            }
        });
        
        // ESC键关闭
        document.addEventListener('keydown', (e) => {
            if (e.key === 'Escape' && settingsModal.classList.contains('show')) {
                closeSettingsModal();
            }
        });
        
        // 设置侧边栏切换功能
        const settingsSidebarItems = document.querySelectorAll('.settings-sidebar-item');
        const settingsTabContents = document.querySelectorAll('.settings-tab-content');
        
        settingsSidebarItems.forEach(item => {
            item.addEventListener('click', () => {
                const targetTab = item.dataset.tab;
                
                // 移除所有活动状态
                settingsSidebarItems.forEach(i => i.classList.remove('active'));
                settingsTabContents.forEach(c => c.classList.remove('active'));
                
                // 添加当前活动状态
                item.classList.add('active');
                const targetContent = document.getElementById(`${targetTab}-tab`);
                if (targetContent) {
                    targetContent.classList.add('active');
                }
            });
        });
        
    
        // 把这些颜色控件打包传给颜色模块
        const colorElements = {
            brightnessSlider,
            brightnessValue,
            exposureSlider,
            exposureValue,
            saturationSlider,
            saturationValue,
            contrastSlider,
            contrastValue,
            redTintSlider,
            greenTintSlider,
            blueTintSlider,
            redTintValue,
            greenTintValue,
            blueTintValue,
            highlightsSlider,
            highlightsValue,
            shadowsSlider,
            shadowsValue,
            whitesSlider,
            whitesValue
        };
        
        // 初始化颜色模块
        initColorModule(colorElements);
        
        // 默认参数配置
        const defaultSettings = {
            use_auto_wb: 1,
            use_camera_wb: 0,
            bright: 1.0,
            exp_shift: 0.0,
            user_sat: 100,
            fbdd_noiserd: 0,
            user_mul: [1.0, 1.0, 1.0, 1.0],
            output_color: 1,
            output_bps: 8,
            half_size: 0,
            exp_correc: 1,
            adjust_maximum_thr: 0.75,
            shadows: 0
        };
        
      
        
        // 当前使用的参数
        let settings = { ...defaultSettings };
        
        // 当前加载的文件数据
        let currentFileBuffer = null;
        // 处理完的图像数据，存这能避免重复计算
        let cachedImageData = null;
        // 颜色替换后的基础图像，后续调色就基于这个，不会累积变化
        let colorReplaceBaseImageData = null;
        
        // 降噪的参数设置
        let currentNoiseReductionSettings = {
            type: 'mean',
            detailPreservation: 50
        };

        // 初始化LibRaw处理器
        const libraw = new LibRaw();
        
        // 从Basic.js拿基础函数，debounce改个名字免得重名
        const { debounce: debounceUtil, readFileAsArrayBuffer, updateImageFromCache: basicUpdateImageFromCache } = await import('./Files/Basic.js');
        
        
        // 记住当前选中的文件
        let currentSelectedFile;
        
        // 图像更新函数，防抖处理避免卡顿（带直方图更新）
        const debouncedImageUpdateWithHistogram = debounceUtil(async () => {
            if (cachedImageData) {
                await updateImageFromCache(cachedImageData, cachedImageData.width, cachedImageData.height, ctx, canvas, applyAdjustmentsToCachedData);
                
                // 更新直方图显示
                if (window.chartManager) {
                    window.chartManager.forceUpdateHistogram();
                }
                refreshImageDetails();
            }
        }, 80); // 80毫秒延迟，既流畅又不会太频繁
        
        // 别名，保持向后兼容
        const debouncedImageUpdate = debouncedImageUpdateWithHistogram;
        
        // 标记滑块是否正在拖动
        let isSliderDragging = false;
        
        // 监听锐化滑块的鼠标事件
        sharpnessSlider.addEventListener('mousedown', () => {
            isSliderDragging = true;
        });
        
        sharpnessSlider.addEventListener('mouseup', () => {
            isSliderDragging = false;
            // 松开鼠标后立即应用处理
            debouncedImageUpdateWithHistogram();
        });
        
        // 移动端触摸事件
        sharpnessSlider.addEventListener('touchstart', () => {
            isSliderDragging = true;
        });
        
        sharpnessSlider.addEventListener('touchend', () => {
            isSliderDragging = false;
            // 触摸结束后立即应用处理
            debouncedImageUpdateWithHistogram();
        });
        
        // 把这个标志暴露出去，给Details.js用
        window.isSliderDragging = () => isSliderDragging;
        
     
        
        // 把所有参数恢复到默认值
        function resetAllParametersToDefault() {
            // 恢复基础调色参数
            brightnessSlider.value = 1.0;
            brightnessValue.textContent = '1.0';
            settings.bright = 1.0;
            
            exposureSlider.value = 0;
            exposureValue.textContent = '0.0';
            settings.exp_shift = 0;
            
            saturationSlider.value = 100;
            saturationValue.textContent = '100';
            settings.user_sat = 100;
            
            contrastSlider.value = 0;
            contrastValue.textContent = '0';
            settings.contrast = 0;
            
            // 恢复颜色调整参数
            highlightsSlider.value = 0;
            highlightsValue.textContent = '0';
            settings.highlights = 0;
            
            shadowsSlider.value = 0;
            shadowsValue.textContent = '0';
            settings.shadows = 0;
            
            redTintSlider.value = 0;
            redTintValue.textContent = '0';
            settings.redTint = 0;
            
            greenTintSlider.value = 0;
            greenTintValue.textContent = '0';
            settings.greenTint = 0;
            
            blueTintSlider.value = 0;
            blueTintValue.textContent = '0';
            settings.blueTint = 0;
            
            whitesSlider.value = 100;
            whitesValue.textContent = '100';
            settings.whites = 100;
            
            // 恢复白平衡设置
            settings.user_mul = [1.0, 1.0, 1.0, 1.0];
            
            // 恢复细节处理参数
            sharpnessSlider.value = 0;
            sharpnessValue.textContent = '0';
            settings.sharpness = 0;
            
            noiseReductionSlider.value = 0;
            noiseReductionValue.textContent = '0';
            settings.fbdd_noiserd = 0;
            
            textureSlider.value = 0;
            textureValue.textContent = '0';
            
            // 恢复面部美白参数
            faceBrighteningSlider.value = 0;
            faceBrighteningValue.textContent = '0';
            settings.faceBrightening = 0;
            
            faceSmoothnessSlider.value = 50;
            faceSmoothnessValue.textContent = '50';
            settings.faceSmoothness = 50;
            
            
            // 恢复白平衡选项
            useAutoWbCheckbox.checked = true;
            useCameraWbCheckbox.checked = false;
            settings.use_auto_wb = 1;
            settings.use_camera_wb = 0;
            
            // 恢复降噪参数
            currentNoiseReductionSettings = {
                type: 'mean',
                detailPreservation: 50
            };
            detailPreservationSlider.value = 50;
            detailPreservationValue.textContent = '50';
            noiseReductionTypeSelect.value = 'mean';
        }


        // 缓存相关，避免重复处理
        let lastProcessedSettings = null;
        let processedImageData = null;
        
        // 对缓存的图像数据应用各种调整
        function applyAdjustmentsToCachedData(data, width, height) {
            // 把当前所有设置存一份，方便对比
            const currentSettings = {
                bright: settings.bright,
                exp_shift: settings.exp_shift,
                user_sat: settings.user_sat,
                contrast: settings.contrast !== undefined ? settings.contrast : parseInt(contrastSlider.value),
                highlights: settings.highlights !== undefined ? settings.highlights : parseInt(highlightsSlider.value),
                shadows: settings.shadows !== undefined ? settings.shadows : parseInt(shadowsSlider.value),
                whites: settings.whites !== undefined ? settings.whites : parseInt(whitesSlider.value),
                sharpness: settings.sharpness !== undefined ? settings.sharpness : parseInt(sharpnessSlider.value),
                fbdd_noiserd: settings.fbdd_noiserd !== undefined ? settings.fbdd_noiserd : parseInt(noiseReductionSlider.value),
                noiseType: currentNoiseReductionSettings.type,
                detailPreservation: currentNoiseReductionSettings.detailPreservation,
                faceBrightening: settings.faceBrightening !== undefined ? settings.faceBrightening : parseInt(faceBrighteningSlider.value),
                faceSmoothness: settings.faceSmoothness !== undefined ? settings.faceSmoothness : parseInt(faceSmoothnessSlider.value),
                user_mul: [...settings.user_mul],
                redTint: settings.redTint || 0,
                greenTint: settings.greenTint || 0,
                blueTint: settings.blueTint || 0
            };
            
            // 看看有没有做过颜色替换
            const hasColorReplacements = window.getColorReplaceHistory && window.getColorReplaceHistory().length > 0;
            
            // 做过颜色替换的话，就从替换后的基础图开始调，不然会累积效果
            if (hasColorReplacements) {
                if (colorReplaceBaseImageData && colorReplaceBaseImageData.data) {
                    // 用替换后的基础数据
                    data.set(colorReplaceBaseImageData.data);
                    console.log('使用颜色替换基准数据，避免累积处理');
                } else {
                    // 第一次处理，从Canvas拿当前状态
                    if (canvas.width > 0 && canvas.height > 0) {
                        try {
                            const currentCanvasData = ctx.getImageData(0, 0, canvas.width, canvas.height);
                            if (currentCanvasData && currentCanvasData.data && currentCanvasData.data.length > 0) {
                                data.set(currentCanvasData.data);
                                console.log('首次处理，从当前Canvas状态开始');
                            } else {
                                console.warn('Canvas数据无效，使用原始缓存数据');
                            }
                        } catch (error) {
                            console.error('从Canvas获取数据失败:', error);
                            console.warn('使用原始缓存数据');
                        }
                    } else {
                        console.warn('Canvas尺寸无效，使用原始缓存数据');
                    }
                }
            }
            
            // 检查参数有没有变化
            const settingsChanged = !lastProcessedSettings || 
                JSON.stringify(currentSettings) !== JSON.stringify(lastProcessedSettings);
            
            if (!settingsChanged && processedImageData && !hasColorReplacements) {
                // 参数没变且有缓存，直接用了
                data.set(processedImageData);
                return;
            }
            
            // 开始计时
            const startTime = performance.now();
            
            // 提取处理参数
            const sharpness = currentSettings.sharpness;
            const noiseReduction = currentSettings.fbdd_noiserd;
            const faceBrightening = currentSettings.faceBrightening || 0;
            const faceSmoothness = currentSettings.faceSmoothness || 50;
            const needSharpness = sharpness > 0;
            const needNoiseReduction = noiseReduction > 0;
            const needFaceBrightening = faceBrightening > 0;
            
            // 先调颜色（从color.js模块）
            // 就算做了颜色替换，基础调色还是要的，因为替换只改特定颜色
            applyColorAdjustments(data, width, height, settings);
            
            // 降噪放前面
            if (needNoiseReduction) {
                applyNoiseReduction(
                    data, 
                    width, 
                    height, 
                    noiseReduction, 
                    currentSettings.noiseType,
                    currentSettings.detailPreservation
                );
            }
            
            // 锐化放最后，其他都调完了再锐化
            if (needSharpness) {
                applySharpness(data, width, height, sharpness);
            }
            
            // 面部美白
            if (needFaceBrightening) {
                applyFaceBrightening(data, width, height, faceBrightening, faceSmoothness);
            }
            
            // 存处理结果，但只有没颜色替换时才存，不然会被替换覆盖
            if (!hasColorReplacements) {
                if (!processedImageData) {
                    processedImageData = new Uint8ClampedArray(data.length);
                }
                processedImageData.set(data);
                lastProcessedSettings = currentSettings;
            }
            
            // 计时结束，超过10ms才打印
            const endTime = performance.now();
            if (endTime - startTime > 10) {
                console.log(`图像处理耗时: ${(endTime - startTime).toFixed(2)}ms`);
            }
            
            // 更新图片细节显示
            refreshImageDetails();
        }
        




        
        // 文件选择事件
        rawFileInput.addEventListener('change', async (event) => {
            const file = event.target.files[0];
            if (!file) return;
            
            // 记住选中的文件
            currentSelectedFile = file;
            
            // 显示文件名
            fileName.textContent = file.name;
            
            try {
                // 读取文件
                const arrayBuffer = await readFileAsArrayBuffer(file);
                
                // 转成Uint8Array，方便处理
                currentFileBuffer = new Uint8Array(arrayBuffer);
                
                // 启用各种按钮
                resetButton.disabled = false;
                exportPngButton.disabled = false;
                exportJpegButton.disabled = false;
                fullscreenViewButton.disabled = false;
                
                // 显示处理中状态
                statusMessage.textContent = '正在处理 RAW 文件...';
                metadataOutput.textContent = '正在提取元数据...';
                
                // 用当前设置打开RAW文件
                await libraw.open(currentFileBuffer, settings);
                
                // 读取元数据
                const metadata = await libraw.metadata(true);
                metadataOutput.textContent = JSON.stringify(metadata, null, 2);
                
                // 读取图像数据并缓存
                try {
                    const imageData = await libraw.imageData();
                    if (imageData && imageData.data) {
                        // RGB转RGBA，Canvas需要4通道
                        let rgbaData = imageData.data;
                        if (imageData.colors === 3) {
                            // 3通道转4通道
                            rgbaData = new Uint8ClampedArray(imageData.data.length * 4 / 3);
                            for (let i = 0, j = 0; i < imageData.data.length; i += 3, j += 4) {
                                rgbaData[j] = imageData.data[i];     // R
                                rgbaData[j + 1] = imageData.data[i + 1]; // G
                                rgbaData[j + 2] = imageData.data[i + 2]; // B
                                rgbaData[j + 3] = 255;              // A (不透明)
                            }
                        }
                        
                        // 存到缓存里
                        cachedImageData = {
                            data: new Uint8ClampedArray(rgbaData),
                            width: imageData.width,
                            height: imageData.height
                        };
                    }
                } catch (error) {
                    console.error('缓存图像数据失败:', error);
                }
            // 把图像显示出来
            await updateImageFromCache(cachedImageData, cachedImageData.width, cachedImageData.height, ctx, canvas, applyAdjustmentsToCachedData);
                
                // 隐藏处理中提示
                statusMessage.textContent = '处理完成';
                setTimeout(() => {
                    statusMessage.textContent = '';
                }, 2000);
                
                // 更新细节显示
                refreshImageDetails();
                
                // 更新直方图
                if (window.chartManager) {
                    window.chartManager.forceUpdateHistogram();
                }
            } catch (error) {
                console.error('处理文件时出错:', error);
                statusMessage.textContent = '处理失败';
                metadataOutput.textContent = `处理文件时出错: ${error.message}`;
            }
        });
        
        // 重置按钮
        resetButton.addEventListener('click', () => {
            // 恢复默认参数
            settings = { ...defaultSettings };
            
            // 恢复所有控件到默认值
            useAutoWbCheckbox.checked = true;
            useCameraWbCheckbox.checked = false;
            brightnessSlider.value = 1.0;
            brightnessValue.textContent = '1.0';
            exposureSlider.value = 0.0;
            exposureValue.textContent = '0.0';
            saturationSlider.value = 100;
            saturationValue.textContent = '100';
            sharpnessSlider.value = 0;
            sharpnessValue.textContent = '0';
            noiseReductionSlider.value = 0;
            noiseReductionValue.textContent = '0';
            noiseReductionTypeSelect.value = 'mean';
            detailPreservationSlider.value = 50;
            detailPreservationValue.textContent = '50';
            textureSlider.value = 0;
            textureValue.textContent = '0';
            faceBrighteningSlider.value = 0;
            faceBrighteningValue.textContent = '0';
            faceSmoothnessSlider.value = 50;
            faceSmoothnessValue.textContent = '50';
            contrastSlider.value = 0;
            contrastValue.textContent = '0';
            redTintSlider.value = 0;
            greenTintSlider.value = 0;
            blueTintSlider.value = 0;
            highlightsSlider.value = 0;
            shadowsSlider.value = 0;
            whitesSlider.value = 100;
            whitesValue.textContent = '100';
            
            // 恢复降噪参数
            currentNoiseReductionSettings = {
                type: 'mean',
                detailPreservation: 50
            };
            
            // 重新处理图像
            updateImageWithNewSettings();
        });
    
        
        // 初始化降噪控件显示
        detailPreservationValue.textContent = detailPreservationSlider.value;
        
        // 初始化滑块管理器
        initSliderManager();
        
        // 准备颜色替换功能需要的元素
        const colorReplaceElements = {
            colorRangeStart: document.getElementById('color-range-start'),
            colorRangeEnd: document.getElementById('color-range-end'),
            colorSlider1: document.getElementById('colorSlider1'),
            colorSlider2: document.getElementById('colorSlider2'),
            colorGradientTrack: document.getElementById('colorGradientTrack'),
            colorRangeContainer: document.getElementById('colorRangeContainer'),
            targetColorStart: document.getElementById('target-color-start'),
            targetColorEnd: document.getElementById('target-color-end'),
            targetColorGradientTrack: document.getElementById('targetColorGradientTrack'),
            targetColorRangeContainer: document.getElementById('targetColorRangeContainer'),
            mixRatio: document.getElementById('mixRatio'),
            mixRatioValue: document.getElementById('mixRatio-value'),
            colorTolerance: document.getElementById('colorTolerance'),
            colorToleranceValue: document.getElementById('colorTolerance-value'),
            previewColorReplace: document.getElementById('previewColorReplace'),
            applyColorReplace: document.getElementById('applyColorReplace'),
            undoColorReplace: document.getElementById('undoColorReplace'),
            colorReplaceResult: document.getElementById('colorReplaceResult'),
            replacedPixelsCount: document.getElementById('replacedPixelsCount'),
            colorReplaceTableBody: document.getElementById('colorReplaceTableBody')
        };
        
        const colorReplaceCanvas = {
            ctx: ctx,
            canvas: canvas
        };
        
        // 初始化颜色替换
        initColorReplace(colorReplaceElements, colorReplaceCanvas, debouncedImageUpdate);
        
        // 批量给滑块加事件监听
        addSliderEventListenersBatch([
            {
                element: brightnessSlider,
                callback: (e) => {
                    settings.bright = parseFloat(e.target.value);
                    brightnessValue.textContent = settings.bright.toFixed(1);
                    debouncedImageUpdateWithHistogram();
                }
            },
            {
                element: exposureSlider,
                callback: (e) => {
                    settings.exp_shift = parseFloat(e.target.value);
                    exposureValue.textContent = settings.exp_shift.toFixed(1);
                    debouncedImageUpdateWithHistogram();
                }
            },
            {
                element: noiseReductionSlider,
                callback: (e) => {
                    settings.fbdd_noiserd = parseInt(e.target.value);
                    noiseReductionValue.textContent = settings.fbdd_noiserd;
                    debouncedImageUpdateWithHistogram();
                }
            },
            {
                element: noiseReductionTypeSelect,
                callback: (e) => {
                    currentNoiseReductionSettings.type = e.target.value;
                    debouncedImageUpdateWithHistogram();
                },
                eventType: 'change'
            },
            {
                element: detailPreservationSlider,
                callback: (e) => {
                    currentNoiseReductionSettings.detailPreservation = parseInt(e.target.value);
                    detailPreservationValue.textContent = currentNoiseReductionSettings.detailPreservation;
                    debouncedImageUpdateWithHistogram();
                }
            }
        ]);
        
 
        
        // 标签页切换逻辑
        tabs.forEach(tab => {
            tab.addEventListener('click', () => {
                // 先把所有标签页都取消激活
                tabs.forEach(t => t.classList.remove('active'));
                tabContents.forEach(c => c.classList.remove('active'));
                
                // 激活当前标签页
                tab.classList.add('active');
                document.getElementById(`${tab.dataset.tab}-tab`).classList.add('active');
            });
        });
        

        
        // 颜色调整防抖处理
        const debouncedColorUpdate = debounceUtil(() => {
            updateWhiteBalanceCoefficients(settings);
            // 不管有没有缓存，都更新图像
            debouncedImageUpdateWithHistogram();
        }, 150); // 150ms延迟，平衡流畅度和性能
        
        // 注册所有颜色调整的事件监听
        registerColorEventListeners(settings, debouncedImageUpdateWithHistogram, debouncedColorUpdate);
        
        // 给剩下的滑块加事件监听
        addSliderEventListenersBatch([
            {
                element: sharpnessSlider,
                callback: (e) => {
                    sharpnessValue.textContent = e.target.value;
                    debouncedImageUpdateWithHistogram();
                }
            },
            {
                element: textureSlider,
                callback: (e) => {
                    textureValue.textContent = e.target.value;
                    debouncedImageUpdateWithHistogram();
                }
            },
            {
                element: faceBrighteningSlider,
                callback: (e) => {
                    settings.faceBrightening = parseInt(e.target.value);
                    faceBrighteningValue.textContent = e.target.value;
                    debouncedImageUpdateWithHistogram();
                }
            },
            {
                element: faceSmoothnessSlider,
                callback: (e) => {
                    settings.faceSmoothness = parseInt(e.target.value);
                    faceSmoothnessValue.textContent = e.target.value;
                    debouncedImageUpdateWithHistogram();
                }
            }
        ]);
        

        
        // updateImageFromCache的无参数版本
        async function updateImageFromCache() {
            // 有缓存就用缓存的更新函数
            if (cachedImageData) {
                await basicUpdateImageFromCache(cachedImageData, cachedImageData.width, cachedImageData.height, ctx, canvas, applyAdjustmentsToCachedData);
            } else {
                // 没缓存就调用updateImage
                await updateImage();
            }
        }

        // 用新设置更新图像
        async function updateImageWithNewSettings() {
            if (!currentSelectedFile) return;
            
            try {
                statusMessage.textContent = '应用设置...';
                
                // 重新读文件，避免ArrayBuffer被分离的问题
                const arrayBuffer = await readFileAsArrayBuffer(currentSelectedFile);
                const bufferCopy = new Uint8Array(arrayBuffer);
                
                // 用新设置重新打开
                await libraw.open(bufferCopy, settings);
                
                // 更新显示
                await updateImageFromCache();
                
                // 更新细节显示
                refreshImageDetails();
                
                statusMessage.textContent = '设置已应用';
                setTimeout(() => {
                    statusMessage.textContent = '';
                }, 1500);
            } catch (error) {
                console.error('应用新设置时出错:', error);
                statusMessage.textContent = '应用设置失败';
            }
        }
        
        // 更新图像显示
        async function updateImage() {
            try {
                // 有缓存优先用缓存
                if (cachedImageData && cachedImageData.data) {
                    // 直接用缓存数据渲染
                    await updateImageFromCache(cachedImageData, cachedImageData.width, cachedImageData.height, ctx, canvas, applyAdjustmentsToCachedData);
                    return;
                }
                
                // 没缓存就从libraw拿
                const imageData = await libraw.imageData();
                
                if (!imageData || !imageData.data) {
                    console.error('无法获取图像数据');
                    return;
                }
                
                // 设置Canvas大小
                canvas.width = imageData.width;
                canvas.height = imageData.height;
                
                // RGB转RGBA格式转换
                if (imageData.colors === 3) {
                    // 3通道转4通道
                    const rgbaData = new Uint8ClampedArray(imageData.data.length * 4 / 3);
                    for (let i = 0, j = 0; i < imageData.data.length; i += 3, j += 4) {
                        rgbaData[j] = imageData.data[i];     // R
                        rgbaData[j + 1] = imageData.data[i + 1]; // G
                        rgbaData[j + 2] = imageData.data[i + 2]; // B
                        rgbaData[j + 3] = 255;              // A (不透明)
                    }
                    
                    // 调对比度
                    const contrast = parseInt(contrastSlider.value);
                    if (contrast !== 0) {
                        applyContrast(rgbaData, contrast);
                    }
                    
                    // 降噪在applyAdjustmentsToCachedData里处理了，这里不用重复
                    
                    // 调锐化和清晰度
                    const sharpness = parseInt(sharpnessSlider.value);
                    const texture = parseInt(textureSlider.value);
                    if (sharpness > 0 || texture > 0) {
                        applyUnsharpMask(rgbaData, imageData.width, imageData.height, sharpness, texture);
                    }
                    
                    // 创建ImageData
                    const canvasImageData = ctx.createImageData(imageData.width, imageData.height);
                    canvasImageData.data.set(rgbaData);
                    
                    // 画到Canvas上
                    ctx.putImageData(canvasImageData, 0, 0);
                } else {
                    // 已经是4通道了
                    const canvasImageData = ctx.createImageData(imageData.width, imageData.height);
                    canvasImageData.data.set(imageData.data);
                    ctx.putImageData(canvasImageData, 0, 0);
                }
            } catch (error) {
                console.error('更新图像时出错:', error);
            }
        }
        

        

        

        
        // 准备滤镜模块需要的元素
        const filterElements = {
            filterSelect,
            saveFilterButton,
            rawFileInput,
            resetButton,
            brightnessSlider,
            brightnessValue,
            exposureSlider,
            exposureValue,
            saturationSlider,
            saturationValue,
            contrastSlider,
            contrastValue,
            highlightsSlider,
            highlightsValue,
            shadowsSlider,
            shadowsValue,
            redTintSlider,
            redTintValue,
            greenTintSlider,
            greenTintValue,
            blueTintSlider,
            blueTintValue,
            whitesSlider,
            whitesValue,
            sharpnessSlider,
            sharpnessValue,
            noiseReductionSlider,
            noiseReductionValue,
            faceBrighteningSlider,
            faceBrighteningValue,
            faceSmoothnessSlider,
            faceSmoothnessValue
        };
        
        const filterManager = initFilterModule(
            filterElements,
            settings,
            resetAllParametersToDefault,
            () => {
                // 更新图像和直方图
                debouncedImageUpdate();
                if (window.chartManager) {
                    window.chartManager.forceUpdateHistogram();
                }
            },
            updateWhiteBalanceCoefficients
        );
        
        // 全屏查看大图功能
        // 创建全屏预览弹窗
        function createFullscreenModal() {
            // 已经存在就直接返回
            if (document.getElementById('fullscreen-modal')) {
                return document.getElementById('fullscreen-modal');
            }
            
            // 创建弹窗容器
            const modal = document.createElement('div');
            modal.id = 'fullscreen-modal';
            modal.style.position = 'fixed';
            modal.style.top = '0';
            modal.style.left = '0';
            modal.style.width = '100%';
            modal.style.height = '100%';
            modal.style.backgroundColor = 'rgba(0, 0, 0, 0.9)';
            modal.style.display = 'none';
            modal.style.justifyContent = 'center';
            modal.style.alignItems = 'center';
            modal.style.zIndex = '1000';
            modal.style.cursor = 'pointer';
            modal.style.transition = 'opacity 0.3s ease';
            
            // 创建关闭按钮
            const closeButton = document.createElement('button');
            closeButton.textContent = '×';
            closeButton.style.position = 'absolute';
            closeButton.style.top = '20px';
            closeButton.style.right = '30px';
            closeButton.style.fontSize = '40px';
            closeButton.style.color = 'white';
            closeButton.style.backgroundColor = 'transparent';
            closeButton.style.border = 'none';
            closeButton.style.cursor = 'pointer';
            closeButton.style.outline = 'none';
            closeButton.style.userSelect = 'none';
            closeButton.style.zIndex = '1001';
            
            // 创建图像容器
            const imageWrapper = document.createElement('div');
            imageWrapper.style.maxWidth = '90%';
            imageWrapper.style.maxHeight = '90%';
            imageWrapper.style.overflow = 'hidden';
            
            // 创建显示大图的canvas
            const fullscreenCanvas = document.createElement('canvas');
            fullscreenCanvas.id = 'fullscreen-canvas';
            fullscreenCanvas.style.maxWidth = '100%';
            fullscreenCanvas.style.maxHeight = '100vh';
            fullscreenCanvas.style.boxShadow = '0 0 30px rgba(255, 255, 255, 0.3)';
            
            // 组装DOM
            imageWrapper.appendChild(fullscreenCanvas);
            modal.appendChild(closeButton);
            modal.appendChild(imageWrapper);
            document.body.appendChild(modal);
            
            // 绑定关闭事件
            function closeModal() {
                modal.style.opacity = '0';
                setTimeout(() => {
                    modal.style.display = 'none';
                }, 300);
            }
            
            closeButton.addEventListener('click', closeModal);
            modal.addEventListener('click', (e) => {
                if (e.target === modal) {
                    closeModal();
                }
            });
            
            // ESC键关闭
            document.addEventListener('keydown', (e) => {
                if (e.key === 'Escape' && modal.style.display === 'flex') {
                    closeModal();
                }
            });
            
            return modal;
        }
        
        // 显示全屏预览
        function showFullscreenPreview() {
            // 检查Canvas是否有效
            if (!canvas || canvas.width === 0 || canvas.height === 0) {
                return;
            }
            
            // 创建或获取弹窗
            const modal = createFullscreenModal();
            const fullscreenCanvas = document.getElementById('fullscreen-canvas');
            // 用sRGB颜色空间，和主canvas保持一致
            const fullscreenCtx = fullscreenCanvas.getContext('2d', { colorSpace: 'srgb' });
            
            // 全屏canvas大小和当前Canvas一样
            fullscreenCanvas.width = canvas.width;
            fullscreenCanvas.height = canvas.height;
            
            // 从当前Canvas拿图像数据，包含所有修改
            const currentImageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
            
            // 画到全屏canvas上
            fullscreenCtx.clearRect(0, 0, fullscreenCanvas.width, fullscreenCanvas.height);
            fullscreenCtx.putImageData(currentImageData, 0, 0);
            
            // 显示弹窗
            modal.style.display = 'flex';
            // 强制重排，触发过渡动画
            void modal.offsetWidth;
            modal.style.opacity = '1';
        }
        
 
        
        // 全屏查看按钮
        fullscreenViewButton.addEventListener('click', showFullscreenPreview);
        
        // Canvas图像数据缓存
        let cachedCanvasImageData = null;
        let lastCanvasUpdateTime = 0;
        
        // 获取Canvas图像数据，带缓存优化
        function getCanvasImageData() {
            const now = performance.now();
            // 100ms内的缓存直接返回
            if (cachedCanvasImageData && (now - lastCanvasUpdateTime) < 100) {
                return cachedCanvasImageData;
            }
            
            // 重新获取
            cachedCanvasImageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
            lastCanvasUpdateTime = now;
            return cachedCanvasImageData;
        }
        
        // 图片细节显示功能（优化版）
        function showImageDetails(mouseX, mouseY) {
            if (!cachedImageData || !cachedImageData.data) {
                return;
            }
            
            // 节流控制
            const now = performance.now();
            if (now - lastUpdateTime < UPDATE_THROTTLE) {
                return;
            }
            lastUpdateTime = now;
            
            // 计算在Canvas上的相对位置
            const canvasRect = canvas.getBoundingClientRect();
            const scaleX = canvas.width / canvasRect.width;
            const scaleY = canvas.height / canvasRect.height;
            
            let canvasX, canvasY;
            
            if (isDetailFixed) {
                // 使用固定位置
                canvasX = fixedPosition.x;
                canvasY = fixedPosition.y;
            } else {
                // 使用鼠标位置
                canvasX = Math.floor((mouseX - canvasRect.left) * scaleX);
                canvasY = Math.floor((mouseY - canvasRect.top) * scaleY);
            }
            
            // 确保坐标在有效范围内
            if (canvasX < 0 || canvasX >= canvas.width || canvasY < 0 || canvasY >= canvas.height) {
                return;
            }
            
            // 使用缓存的Canvas图像数据
            const currentImageData = getCanvasImageData();
            const pixelIndex = (canvasY * canvas.width + canvasX) * 4;
            const r = currentImageData.data[pixelIndex];
            const g = currentImageData.data[pixelIndex + 1];
            const b = currentImageData.data[pixelIndex + 2];
            const a = currentImageData.data[pixelIndex + 3];
            
            // 更新像素信息显示
            pixelPosition.textContent = `${canvasX}, ${canvasY}`;
            pixelRgb.textContent = `(${r}, ${g}, ${b})`;
            
            // 计算亮度 (使用标准亮度公式)
            const brightness = Math.round(0.299 * r + 0.587 * g + 0.114 * b);
            pixelBrightness.textContent = brightness;
            
            // 计算色相
            const hue = calculateHue(r, g, b);
            pixelHue.textContent = `${hue}°`;
            
            // 创建放大预览（异步执行，避免阻塞）
            requestAnimationFrame(() => {
                createZoomPreview(canvasX, canvasY);
            });
        }
        
        // 计算色相的函数
        function calculateHue(r, g, b) {
            const max = Math.max(r, g, b);
            const min = Math.min(r, g, b);
            const delta = max - min;
            
            if (delta === 0) return 0;
            
            let hue = 0;
            if (max === r) {
                hue = ((g - b) / delta) % 6;
            } else if (max === g) {
                hue = (b - r) / delta + 2;
            } else {
                hue = (r - g) / delta + 4;
            }
            
            hue = Math.round(hue * 60);
            return hue < 0 ? hue + 360 : hue;
        }
        
        // 创建放大预览（优化版）
        function createZoomPreview(centerX, centerY) {
            const zoomCtx = zoomCanvas.getContext('2d', { colorSpace: 'srgb' });
            const zoomSize = 100; // 放大区域大小
            const zoomFactor = 4; // 放大倍数
            
            // 计算源区域
            const sourceX = Math.max(0, centerX - zoomSize / 2);
            const sourceY = Math.max(0, centerY - zoomSize / 2);
            const sourceWidth = Math.min(zoomSize, canvas.width - sourceX);
            const sourceHeight = Math.min(zoomSize, canvas.height - sourceY);
            
            // 使用缓存的Canvas数据，避免重复获取
            const currentImageData = getCanvasImageData();
            
            // 创建临时canvas来绘制放大区域
            const tempCanvas = document.createElement('canvas');
            tempCanvas.width = sourceWidth;
            tempCanvas.height = sourceHeight;
            const tempCtx = tempCanvas.getContext('2d', { colorSpace: 'srgb' });
            
            // 从缓存的图像数据中提取区域
            const sourceImageData = new ImageData(sourceWidth, sourceHeight);
            for (let y = 0; y < sourceHeight; y++) {
                for (let x = 0; x < sourceWidth; x++) {
                    const srcIndex = ((sourceY + y) * canvas.width + (sourceX + x)) * 4;
                    const dstIndex = (y * sourceWidth + x) * 4;
                    sourceImageData.data[dstIndex] = currentImageData.data[srcIndex];
                    sourceImageData.data[dstIndex + 1] = currentImageData.data[srcIndex + 1];
                    sourceImageData.data[dstIndex + 2] = currentImageData.data[srcIndex + 2];
                    sourceImageData.data[dstIndex + 3] = currentImageData.data[srcIndex + 3];
                }
            }
            
            tempCtx.putImageData(sourceImageData, 0, 0);
            
            // 清空并绘制到放大canvas
            zoomCtx.clearRect(0, 0, zoomCanvas.width, zoomCanvas.height);
            zoomCtx.imageSmoothingEnabled = false; // 保持像素清晰
            zoomCtx.drawImage(tempCanvas, 0, 0, sourceWidth * zoomFactor, sourceHeight * zoomFactor);
            
            // 绘制中心十字线
            const centerPixelX = (centerX - sourceX) * zoomFactor;
            const centerPixelY = (centerY - sourceY) * zoomFactor;
            
            zoomCtx.strokeStyle = '#ff0000';
            zoomCtx.lineWidth = 1;
            zoomCtx.beginPath();
            zoomCtx.moveTo(centerPixelX, 0);
            zoomCtx.lineTo(centerPixelX, zoomCanvas.height);
            zoomCtx.moveTo(0, centerPixelY);
            zoomCtx.lineTo(zoomCanvas.width, centerPixelY);
            zoomCtx.stroke();
        }
        
        // 初始化图片细节面板
        function initializeImageDetailPanel() {
            pixelPosition.textContent = '请上传图片';
            pixelRgb.textContent = '-';
            pixelBrightness.textContent = '-';
            pixelHue.textContent = '-';
            
            // 清空放大预览
            const zoomCtx = zoomCanvas.getContext('2d', { colorSpace: 'srgb' });
            zoomCtx.clearRect(0, 0, zoomCanvas.width, zoomCanvas.height);
            zoomCtx.fillStyle = '#f8f9fa';
            zoomCtx.fillRect(0, 0, zoomCanvas.width, zoomCanvas.height);
            zoomCtx.fillStyle = '#6c757d';
            zoomCtx.font = '14px Arial';
            zoomCtx.textAlign = 'center';
            zoomCtx.fillText('无图片', zoomCanvas.width / 2, zoomCanvas.height / 2);
            
            // 初始化模式状态
            isDetailFixed = false;
            updateDetailModeIndicator();
        }
        
        // 初始化面板
        initializeImageDetailPanel();
        
        
        
        // 切换固定/跟随模式
        function toggleDetailMode(mouseX, mouseY) {
            if (!cachedImageData || !cachedImageData.data) {
                return;
            }
            
            if (isDetailFixed) {
                // 当前是固定模式，切换到跟随模式
                isDetailFixed = false;
                updateDetailModeIndicator();
            } else {
                // 当前是跟随模式，切换到固定模式
                const canvasRect = canvas.getBoundingClientRect();
                const scaleX = canvas.width / canvasRect.width;
                const scaleY = canvas.height / canvasRect.height;
                
                fixedPosition.x = Math.floor((mouseX - canvasRect.left) * scaleX);
                fixedPosition.y = Math.floor((mouseY - canvasRect.top) * scaleY);
                
                // 确保坐标在有效范围内
                if (fixedPosition.x >= 0 && fixedPosition.x < canvas.width && 
                    fixedPosition.y >= 0 && fixedPosition.y < canvas.height) {
                    isDetailFixed = true;
                    updateDetailModeIndicator();
                }
            }
        }
        
        // 更新模式指示器
        function updateDetailModeIndicator() {
            const modeText = isDetailFixed ? '固定模式' : '跟随模式';
            const header = document.querySelector('.detail-header h4');
            header.textContent = `图片细节 - ${modeText}`;
            
            // 添加视觉反馈
            if (isDetailFixed) {
                imageDetailPanel.style.borderColor = '#e74c3c';
                imageDetailPanel.style.borderWidth = '2px';
            } else {
                imageDetailPanel.style.borderColor = 'var(--border-color)';
                imageDetailPanel.style.borderWidth = '1px';
            }
        }
        
        // 刷新图片细节显示
        function refreshImageDetails() {
            // 清除Canvas数据缓存，强制获取最新数据
            cachedCanvasImageData = null;
            lastCanvasUpdateTime = 0;
            
            if (isDetailFixed) {
                // 如果是固定模式，使用固定位置刷新
                const canvasRect = canvas.getBoundingClientRect();
                const mouseX = canvasRect.left + (fixedPosition.x * canvasRect.width / canvas.width);
                const mouseY = canvasRect.top + (fixedPosition.y * canvasRect.height / canvas.height);
                showImageDetails(mouseX, mouseY);
            }
            // 跟随模式不需要主动刷新，会在鼠标移动时自动更新
        }
        
        // 为Canvas添加鼠标事件（优化版）
        canvas.addEventListener('mousemove', (e) => {
            // 使用requestAnimationFrame来优化性能
            requestAnimationFrame(() => {
                showImageDetails(e.clientX, e.clientY);
            });
        }, { passive: true });
        
        canvas.addEventListener('click', (e) => {
            toggleDetailMode(e.clientX, e.clientY);
        });
        
        // 导出按钮事件监听器
        exportPngButton.addEventListener('click', async () => {
            try {
                // 使用当前文件名（如果有）或默认名称
                const baseFilename = currentSelectedFile ? currentSelectedFile.name.replace(/\.[^/.]+$/, '') : 'exported-image';
                
                // 检查是否有颜色替换历史记录
                const hasColorReplacements = window.getColorReplaceHistory && window.getColorReplaceHistory().length > 0;
                
                if (!hasColorReplacements) {
                    // 没有颜色替换时，正常处理图像调整
                    statusMessage.textContent = '正在应用所有颜色调整...';
                    updateWhiteBalanceCoefficients(settings);
                    await updateImageFromCache();
                } else {
                    // 有颜色替换时，直接导出当前Canvas状态
                    statusMessage.textContent = '正在导出 PNG 图像（包含颜色替换）...';
                }
                
                statusMessage.textContent = '正在导出 PNG 图像...';
                await exportPNG(canvas, baseFilename);
                
                statusMessage.textContent = 'PNG 图像导出成功';
                setTimeout(() => {
                    statusMessage.textContent = '';
                }, 2000);
            } catch (error) {
                console.error('导出 PNG 图像失败:', error);
                statusMessage.textContent = '导出 PNG 图像失败';
                setTimeout(() => {
                    statusMessage.textContent = '';
                }, 2000);
            }
        });
        
        exportJpegButton.addEventListener('click', async () => {
            try {
                // 使用当前文件名（如果有）或默认名称
                const baseFilename = currentSelectedFile ? currentSelectedFile.name.replace(/\.[^/.]+$/, '') : 'exported-image';
                
                // 检查是否有颜色替换历史记录
                const hasColorReplacements = window.getColorReplaceHistory && window.getColorReplaceHistory().length > 0;
                
                if (!hasColorReplacements) {
                    // 没有颜色替换时，正常处理图像调整
                    statusMessage.textContent = '正在应用所有颜色调整...';
                    updateWhiteBalanceCoefficients(settings);
                    await updateImageFromCache();
                } else {
                    // 有颜色替换时，直接导出当前Canvas状态
                    statusMessage.textContent = '正在导出 JPEG 图像（包含颜色替换）...';
                }
                
                statusMessage.textContent = '正在导出 JPEG 图像...';
                await exportJPEG(canvas, 0.9, baseFilename);
                
                statusMessage.textContent = 'JPEG 图像导出成功';
                setTimeout(() => {
                    statusMessage.textContent = '';
                }, 2000);
            } catch (error) {
                console.error('导出 JPEG 图像失败:', error);
                statusMessage.textContent = '导出 JPEG 图像失败';
                setTimeout(() => {
                    statusMessage.textContent = '';
                }, 2000);
            }
        });
        
    
        
        
        // 暴露清除图像处理缓存的方法供颜色替换模块调用
        window.clearImageProcessingCache = function() {
            lastProcessedSettings = null;
            processedImageData = null;
            console.log('已清除图像处理缓存');
        };
        
        // 暴露获取当前Canvas状态的方法
        window.getCurrentCanvasState = function() {
            if (canvas.width > 0 && canvas.height > 0) {
                return ctx.getImageData(0, 0, canvas.width, canvas.height);
            }
            return null;
        };
        
        
        // 保存颜色替换后的基准数据
        window.saveColorReplaceBaseData = function(imageData) {
            colorReplaceBaseImageData = {
                data: new Uint8ClampedArray(imageData.data),
                width: imageData.width,
                height: imageData.height
            };
            console.log('已保存颜色替换基准数据');
        };
        
        // 清除颜色替换基准数据
        window.clearColorReplaceBaseData = function() {
            colorReplaceBaseImageData = null;
            console.log('已清除颜色替换基准数据');
        };
        
        // 重置到颜色替换基准状态（清除所有基本设置调整）
        window.resetToColorReplaceBase = function() {
            if (colorReplaceBaseImageData && colorReplaceBaseImageData.data) {
                // 重置所有基本设置为默认值
                settings.bright = 1.0;
                settings.exp_shift = 0.0;
                settings.user_sat = 100;
                settings.contrast = 0;
                settings.shadows = 0;
                settings.highlights = 0;
                settings.whites = 100;
                settings.user_mul = [1.0, 1.0, 1.0, 1.0];
                
                // 更新UI控件
                brightnessSlider.value = 1.0;
                brightnessValue.textContent = '1.0';
                exposureSlider.value = 0.0;
                exposureValue.textContent = '0.0';
                saturationSlider.value = 100;
                saturationValue.textContent = '100';
                contrastSlider.value = 0;
                contrastValue.textContent = '0';
                shadowsSlider.value = 0;
                shadowsValue.textContent = '0';
                highlightsSlider.value = 0;
                highlightsValue.textContent = '0';
                whitesSlider.value = 100;
                whitesValue.textContent = '100';
                
                // 直接显示基准图像
                const imageData = new ImageData(colorReplaceBaseImageData.data, colorReplaceBaseImageData.width, colorReplaceBaseImageData.height);
                ctx.putImageData(imageData, 0, 0);
                
                // 清除处理缓存
                lastProcessedSettings = null;
                processedImageData = null;
                
                console.log('已重置到颜色替换基准状态');
            } else {
                console.warn('没有颜色替换基准数据可重置');
            }
        };
        
        // 初始化图表模块
        const histogramCanvas = document.getElementById('histogram-canvas');
        const chartOptions = {
            sliders: document.querySelectorAll('input[type="range"]')
        };
        
        window.chartManager = initChartModule(histogramCanvas, canvas, ctx, chartOptions);
    </script>
</body>
</html>